2023-10-18

Use bash? Configure readline!

Annoyed by weird bash behaviour? Tempted to use another shell that offers fancy and shiny features? Then maybe the following tips and tricks will make bash more bearable for you. Turns out bash can behave nicely, you just have to tell it to.

Everyone knows the typical .bashrc tricks, like fancy prompts, aliases and functions. Some may even know set -o vi to enable vi mode (although I have no idea why anyone would consider that useful). Few people however seem to know that readline, the library used by bash and a few other tools with REPL-style interfaces, like python, is configurable as well. Much of the unexpected weirdness you'll encounter when working in bash actually comes from readlines default settings. Perhaps this arcane knowledge has fallen into oblivion because it is canonically documented in GNU texinfo, which has a bit of a bad reputation.

The canonical path for the readline configuration is ~/.inputrc. Thankfully there is an env var to change that:

export INPUTRC="$XDG_CONFIG_HOME/inputrc"

My .profile is full of lines like those. What a time to be alive...

Anyway, let's go over my inputrc line by line. I don't use every possible setting and will explain only those I do use. I'll start with general settings first. At the end there is a spicy section for making completions even cooler.

General Settings

$include /etc/inputrc

This one is optional. It includes your systems default configuration (which may be in a different location on your system (nix users have no right to cry, they chose their pain voluntarily)). Some distributions are sane and change some readline settings, others don't. I am writing this on an arch box, which only sets a few input encoding related settings and enables a few keybinds for terminal emacs to use in the Linux and FreeBSD consoles.

set completion-ignore-case on

Arguable the most impactful setting I use. As the name suggest, it makes completion case insensitive. Here is how using it looks like (the black box is supposed to be the cursor):

$ ls vi  *presses tab*
VID_20190720_154029.mp4   Video/   video-whatever.mp4

So much frustration prevented by just one line in a config file.

set completion-map-case on

This one is a tiny additon to the above option and only works if that one is enabled as well. It makes readline treat - and _ as interchangeable when searching for possible file completions.

set show-all-if-ambiguous on
set show-all-if-unmodified on

Has this ever happened to you: Type something in bash, press tab but nothing happens (except maybe a beep), press tab again and suddenly there are completion suggestions? That is what happens when these options are turned off. Turn them on and completions show up immediately on the first tab press without beeping (the actual explanation of these options is a bit more involved, but I chose to focus on the typical using experience).

set completion-query-items 0

Sometimes bash asks if you really want to see the completion because there are just too many. That might make sense over slow network connections (or more like bad phone line connection back when readline was written), but I am not working remotely. Setting this to zero will give readline consent always to dump all trauma completions onto you, regardless of how many there are.

set page-completions off

If there are a lot of completions, too many to fit on your sad small terminal, they are paged and you have to press space to scroll through them all. Now, my terminal of choice happens to have a scrollback buffer, so I just turn this off.

set bell-style none

No more beeps. You can also set it to visible, but that doesn't do anything in my terminal. The default audible also does nothing in my terminal, but I set this option anyway for good measure.

set blink-matching-paren on

When writing braces or parenthesis, highlight the opening one when you close a pair.

set colored-completion-prefix on

When displaying completion suggestions, this will make readline highlight the common prefix in a different colour. The colour is configured using LS_COLORS, another neat thing people don't seem to know about...

set colored-stats on

When displaying completions suggestions which are files, this will make readline highlight them using the same colours as in ls. Again, colours are configured using LS_COLORS.

set completion-prefix-display-length 5

If the common prefix of completion suggestions is longer than the configured amount of characters, it will be replaced by ellipsis, like this:

$ ls IMG_20221717_  *hits tab*
...abd83e.mp4   ...f323c2.mp4   ...cc212ef.mp4

If you work with long file names often, this is a must have. Oddly sometimes it doesn't work though.

set history-size 5000

Selfexplanatory, I hope.

set horizontal-scroll-mode on

Ah, this is the one that might be a bit controversial. If you, like me, are annoyed by wrapping text, then you'll love this option. It makes readline just scroll horizontally on long input instead of wrapping to the next line.

set mark-directories on

Add / to the names of directories in completion suggestions. This is actually the default, but I faintly remember using a system where this did not happen, so this is yet another option for good measure.

set skip-completed-text on

If triggering a completion while the cursor is in the middle of a word, this makes readline not insert characters that are already present on prompt.

I think this is better shown than explained. Here is what happens when this is turned off:

$ ls Makef *hits tab*
$ ls Makefilekef

And here what happens when it is turned on:

$ ls Makef *hits tab*
$ ls Makefile 

There probably is some historic reason for the default, but it's weird to me that no system I have ever used has turned this on by default.

set visible-stats on

Certain file stats will cause certain characters to be appended to file names in the completion suggestion display. For example, executable files get a *.

"\e[A": history-search-backward
"\e[B": history-search-forward
"\C-p": history-search-backward
"\C-n": history-search-forward

Have you ever looked at one of those modern shells, where you can type the start of a command into the prompt and then just use the arrow keys to cycle to all history entries mathing that prefix? Did you then get jelous because bash, when scrolling through history, ignores anything you have already written into the prompt and as such forces you to use the C-r mode if you want to search for something in the history? Well, with these binds, bash now also has the fancy history scroll functionality. Here both for the up / down arrow keys and also for C-n plus C-p since that is exactly how completions work in kakoune, which I have gotten very used to.

"\C-l": clear-display

By default, C-l is bound to clear-screen. That clears the screen, however just moves everything into scrollback. I perfer clearing the scrollback buffer as well, which clear-display does.

Conditional Settings

You like some of these settings, but only want them to apply to the bash prompt and not other readline based REPLs? Fortunately, there are conditionals in the inputrc syntax.

$if Bash
set bell-style audible
$end

Alternative Completion Paradigm

Ok, so this is how completion works in bash, usually: You type something, you press Tab and if there are multiple possible completions, they are printed below your prompt. The prompt is then duplicated below the suggestions.

$ ls co  *smashes tab*
completion   compare   comedy    contempt

$ ls co 

If you want bash to pick one of the possible completions, you'll have to help it decide by adding more characters to your prompt. Then you'll have to press Tab again.

Readline also supports a different completion paradigm.

"\t": menu-complete
"\e[Z": menu-complete-backward

Now pressing Tab multiple times will cycle through all possible completions. With Shift-Tab you can cycle backwards. The list of possible completions is no longer dumped to the terminal.

You may also want this:

set menu-complete-display-prefix on

Now, this completion paradigm would be a bit too funky for me... but here is where it gets cool: If you additionaly enable the show-all-if-* options from earlier, the list of possible completions will be dumped to the terminal even if menu-complete is used. Since the first press of Tab still does nothing (other than dumping the list), enabling those options turns this completion method from a Very Different Thing™ into just a tiny enhancement to the default completion method. It behaves like you are used to: Pressing Tab either completes until there are no unambigous completions left, or dumps the list of possible completion. Now however, pressing tab again on an ambiguous prefix (or on an empty one) will cycle through all possible completions.

Paste and Undo

These are part of the defaults, but watching people use bash without knowing about them is painful.

You'll hopefully already know about the basic readline editing commands: C-backspace or C-w to delete entire words, C-u to kill from cursor to beginning of line, C-k to kill from cursor to end of line, C-a and C-e to quickly jump to the start / end of the line, M-f and M-b to jump between words, etc..

However, did you know you that if you kill a text region, it gets copied and that you can paste it with C-y?

Want to undo an edit? Just press C-x C-u.

Articles from blogs I read (generated by openring)

whippet lab notebook: guile, heuristics, and heap growth

Greets all! Another brief note today. I have gotten Guile working with one of the Nofl-based collectors, specifically the one that scans all edges conservatively (heap-conservative-mmc / heap-conservative-parallel-mmc). Hurrah!It was a pleasant surprise h…

wingolog, May 22, 2025

Status update, May 2025

Hi! Today wlroots 0.19.0 has finally been released! Among the newly supported protocols, color-management-v1 lays the first stone of HDR support (backend and renderer bits are still being reviewed) and ext-image-copy-capture-v1 enhances the previous screen ca…

emersion, May 15, 2025

Summary of changes for April 2025

Hey everyone!This is the list of all the changes we've done to our projects during the month of April. 100r.co, updated water, ditch bag, woodstove installation, and added new photos and information on first-aid kit. Rabbit Waves, updated Triangular…

Hundred Rabbits, April 30, 2025